package com.ztewatch.wearcontacts.presenter;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.ContentProviderOperation;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Loader;
import android.content.OperationApplicationException;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Groups;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.TextView;

import com.ztewatch.wearcontacts.R;
import com.ztewatch.wearcontacts.data.IConfigLoader;
import com.ztewatch.wearcontacts.data.SortItem;
import com.ztewatch.wearcontacts.loader.GroupListLoaderUtil;
import com.ztewatch.wearcontacts.loader.SortContactsAndGroupLoader;
import com.ztewatch.wearcontacts.view.ILoadCursorDataView;

public class LoadCursorDataPresenter {
	private static final int START_PROGRESS = 0x123;
	private static final int STOP_PROGRESS = 0x124;
	public static final String CONTACT_AND_GROUP_AUTHORITY = "com.android.providers.contacts.groupandcontacts/groupandcontacts";
	public static final Uri CONTACT_AND_GROUP_AUTHORITY_URI = Uri
			.parse("content://" + CONTACT_AND_GROUP_AUTHORITY);
	private ILoadCursorDataView loadCursorDataView;
	private Activity mActivity;
	private IConfigLoader mConfigLoader;
	private List<SortItem> dataSourceList = new ArrayList<SortItem>();
	private AlertDialog mProgressDialog;
	private Handler mHandler = new Handler() {
		public void handleMessage(android.os.Message msg) {
			switch (msg.what) {
			case START_PROGRESS:
				mProgressDialog.show();
				break;
			case STOP_PROGRESS:
				mProgressDialog.dismiss();
				break;
			default:
				break;
			}
		};
	};

	public LoadCursorDataPresenter(Activity activity,
			ILoadCursorDataView iLoadCursorDataView, IConfigLoader configLoader) {
		loadCursorDataView = iLoadCursorDataView;
		mActivity = activity;
		mConfigLoader = configLoader;
		initProgressDialog();
	}

	private void initProgressDialog() {
		AlertDialog.Builder builder = new Builder(mActivity);
		View v = mActivity.getLayoutInflater().inflate(
				R.layout.dialog_message_view, null);
		TextView msg = (TextView) v.findViewById(R.id.dialog_message_title);
		msg.setText("init sort...");
		builder.setView(v);
		mProgressDialog = builder.create();
		setDialogBottomShow(mProgressDialog);
	}

	private void setDialogBottomShow(final AlertDialog alertDialog) {
		Window window = alertDialog.getWindow();
		WindowManager.LayoutParams wmlp = window.getAttributes();
		wmlp.gravity = Gravity.BOTTOM;
		window.setAttributes(wmlp);
		alertDialog.setCancelable(false);
	}
	
	private final LoaderCallbacks<Cursor> loaderCallbacks = new LoaderCallbacks<Cursor>() {

		@Override
		public void onLoaderReset(Loader<Cursor> arg0) {

		}

		@Override
		public void onLoadFinished(Loader<Cursor> arg0, Cursor arg1) {
			if (loadCursorDataView != null) {
				loadCursorDataView.getLoadFinishCursor(arg1);
			}
		}

		@Override
		public Loader<Cursor> onCreateLoader(int id, Bundle args) {
			return mConfigLoader.getConfigLoader();
		}
	};

	public void initLoader(int arg0) {
		mActivity.getLoaderManager().initLoader(arg0, null, loaderCallbacks);
	}

	public void restartLoader(int arg0) {
		mActivity.getLoaderManager().restartLoader(arg0, null, loaderCallbacks);
	}

	public void destroyLoader(int arg0) {
		mActivity.getLoaderManager().destroyLoader(arg0);
	}

	public void updateSort(Cursor c) {
		mHandler.sendEmptyMessage(START_PROGRESS);
		dataSourceList.clear();
		c.moveToPosition(-1);
		while (c.moveToNext()) {
			fillSortListItem(c);
		}
		if (dataSourceList.size() > 1) {// init sort
			saveSortToDatabase(dataSourceList.size() - 1, 1);
		}
		mHandler.sendEmptyMessage(STOP_PROGRESS);
	}

	private void fillSortListItem(Cursor c) {
		int contact_id_index;
		int name_index;
		// int pinned_index;
		int photoId_index;
		int group_id_index;
		// int group_title_index;
		int is_group_index;
		// int sourceid_index;
		int sort_no_index;
		int group_photo_index;
		contact_id_index = c.getColumnIndex(Contacts._ID);
		name_index = c.getColumnIndex(Contacts.DISPLAY_NAME_PRIMARY);
		sort_no_index = c.getColumnIndex(SortContactsAndGroupLoader.SORT_NO);
		photoId_index = c.getColumnIndex(Contacts.PHOTO_ID);
		group_id_index = c.getColumnIndex(Groups._ID);
		is_group_index = c.getColumnIndex(SortContactsAndGroupLoader.IS_GROUP);
		group_photo_index = c.getColumnIndex(Contacts.LOOKUP_KEY);
		// sourceid_index = c.getColumnIndex(Groups.SOURCE_ID);
		// group_title_index = c.getColumnIndex(Groups.TITLE);
		SortItem sortItem = new SortItem();
		if (is_group_index != -1) {
			int is_group = c.getInt(is_group_index);
			sortItem.setIs_group(is_group);
			if (is_group == 0) {// contact
				if (contact_id_index != -1) {
					long id = c.getLong(contact_id_index);
					sortItem.setContact_id(id);
				}
				if (name_index != -1) {
					String name = c.getString(name_index);
					sortItem.setName(name);
				}
				if (sort_no_index != -1) {
					long pinned = c.getLong(sort_no_index);
					sortItem.setPinned(pinned);
				}
				if (photoId_index != -1) {
					long photo_id = c.getLong(photoId_index);
					sortItem.setPhotoId(photo_id);
				}
			} else {// group
				if (group_id_index != -1) {
					long id1 = c.getLong(group_id_index);
					sortItem.setGroup_id(id1);
				}
				if (name_index != -1) {
					String title = c.getString(name_index);
					sortItem.setGroup_title(title);
				}
				if (sort_no_index != -1) {
					long sortno = c.getLong(sort_no_index);
					sortItem.setSort_number(sortno);
				}
				if (group_photo_index != -1) {
					byte[] photoarr = c.getBlob(group_photo_index);
					sortItem.setGroup_photo_arr(photoarr);
				}
			}
		}

		dataSourceList.add(sortItem);
	}

	private void saveSortToDatabase(int from, int to) {
		ArrayList<ContentProviderOperation> contact_operations = new ArrayList<ContentProviderOperation>();
		setReflowedPinningOperations(from, to, contact_operations);

		if (!contact_operations.isEmpty()) {
			// update the database here with the new pinned positions
			try {
				mActivity.getContentResolver().applyBatch(
						ContactsContract.AUTHORITY, contact_operations);
			} catch (RemoteException | OperationApplicationException e) {
			}
		}
	}

	private void setReflowedPinningOperations(int oldPos, int newPinPos,
			ArrayList<ContentProviderOperation> contact_operations) {
		if (oldPos < 0 || newPinPos < 0) {
			return;
		}
		final int lowerBound = Math.min(oldPos, newPinPos);
		final int upperBound = Math.max(oldPos, newPinPos);
		for (int i = lowerBound; i <= upperBound; i++) {
			final SortItem entry = dataSourceList.get(i);

			// final int databasePinnedPosition = i + 1;
			final int databasePinnedPosition = dataSourceList.size() + 1 - i;

			if (entry.getIs_group() == 0) {// contact
				if (entry.getPinned() == databasePinnedPosition)
					continue;
				final Uri uri = Uri.withAppendedPath(Contacts.CONTENT_URI,
						String.valueOf(entry.getContact_id()));
				final ContentValues values = new ContentValues();
				values.put(Contacts.PINNED, databasePinnedPosition);
				contact_operations.add(ContentProviderOperation.newUpdate(uri)
						.withValues(values).build());
				entry.setPinned(databasePinnedPosition);
			} else {// group
				if (entry.getSort_number() == databasePinnedPosition)
					continue;
				final Uri uri = ContentUris.withAppendedId(Groups.CONTENT_URI,
						entry.getGroup_id());
				final ContentValues values = new ContentValues();
				// values.put(Groups.SOURCE_ID, databasePinnedPosition);
				values.put(GroupListLoaderUtil.GROUP_SORT_NUM,
						databasePinnedPosition);
				contact_operations.add(ContentProviderOperation.newUpdate(uri)
						.withValues(values).build());
				entry.setSort_number(databasePinnedPosition);
			}
		}
	}
}
